/*
 * Copyright 2007 Dan Hodge
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.datajanitor.baja.rest.xml;

import java.nio.CharBuffer;
import java.util.Stack;

import net.datajanitor.baja.spi.FileTreeBuilder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class GetTreeResponseHandler extends DefaultHandler {
    private final Log logger = LogFactory.getLog(GetTreeResponseHandler.class);
    private final CharBuffer buffer;
    private final FileTreeBuilder builder;
    private final Stack<Integer> parentFolderIds;
    
    private String getBuffer() {
        char[] ch = new char[this.buffer.position()];
        this.buffer.position(0);
        this.buffer.get(ch);
        
        String contents = new String(ch);
        if (logger.isDebugEnabled()) {
            logger.debug("getBuffer() = " + contents);
        }
        return contents;
    }
    
    public GetTreeResponseHandler(final FileTreeBuilder builder) {
        this.builder = builder;
        this.parentFolderIds = new Stack<Integer>();
        this.parentFolderIds.push(FileTreeBuilder.ROOT_PARENT_DIR_ID);
        this.buffer = CharBuffer.allocate(512);
    }
       
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        AttributeSupport attrs = new AttributeSupport(attributes);
       
        int parentDirId = this.parentFolderIds.peek();
              
        if ("folder".equals(qName)) {
            int dirId = attrs.getAsInt("id");
            String dirName = attrs.get("name");
            this.parentFolderIds.push(dirId);
            
            if (logger.isDebugEnabled()) {
                logger.debug("Handling folder: " + dirName + " (id=" + dirId + ")");
            }
            this.builder.onDirectory(dirId, parentDirId, dirName, attrs.getAsBoolean("shared"));    
        } else if ("file".equals(qName)) {
            int id = attrs.getAsInt("id");
            String name = attrs.get("file_name");
            
            if (logger.isDebugEnabled()) {
                logger.debug("Handling file: " + name + " (id=" + id + ")");
            }
            this.builder.onFile(id, parentDirId, name, attrs.get("keyword"), attrs.getAsBoolean("shared"), attrs.getAsInt("size"), attrs.getAsLong("created"), attrs.getAsLong("updated"));    
        } else if ("tag".equals(qName)) {
            this.builder.onTag(attrs.getAsInt("id"));    
        }
        
        this.buffer.clear();
    }
    
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if ("status".equals(qName)) {
            String status = getBuffer();
            if (!"listing_ok".equals(status)) {
                throw new SAXException("get_account_tree status = " + status);        
            }
        } else if ("folder".equals(qName)) {
            this.builder.onEndDirectory(this.parentFolderIds.pop());
        }
    }
    
    @Override
    public void characters(char[] ch, int offset, int length) {
        if (logger.isDebugEnabled()) {
            String chars = new String(ch, offset, length);
            logger.debug("Adding: " + chars + " to buffer");
        }
        this.buffer.put(ch, offset, length);
    }
}
